/*
 * Copyright (C) 2016 venshine.cn@gmail.com
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.wx.wheelview.widget;

import com.wx.wheelview.ResourceTable;
import com.wx.wheelview.adapter.ArrayWheelAdapter;
import com.wx.wheelview.adapter.BaseWheelAdapter;
import com.wx.wheelview.adapter.SimpleWheelAdapter;
import com.wx.wheelview.common.WheelConstants;
import com.wx.wheelview.common.WheelData;
import com.wx.wheelview.common.WheelViewException;
import com.wx.wheelview.graphics.DrawableFactory;
import com.wx.wheelview.util.TextUtils;
import com.wx.wheelview.util.WheelUtils;

import ohos.agp.components.*;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.text.Font;
import ohos.agp.utils.Color;
import ohos.agp.utils.Rect;
import ohos.agp.utils.TextAlignment;
import ohos.app.Context;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.multimodalinput.event.TouchEvent;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 滚轮控件
 *
 * @author venshine
 */
public class WheelView<T> extends ScrollView implements IWheelView<T>, Component.TouchEventListener,
        Component.LayoutRefreshedListener, Component.DrawTask, ComponentTreeObserver.ScrollChangedListener {
    /**
     * * The constant OFF_SET_DEFAULT
     */
    public static final int OFF_SET_DEFAULT = 1;

    /**
     * The constant Initial y
     */
    private int mInitialY;
    /**
     * The constant Scroller task
     */
    private Runnable mScrollerTask;
    /**
     * The constant New check
     */
    private int mNewCheckDelay = 50;
    /**
     * 偏移量（需要在最前面和最后面补全）
     */
    private int mOffset = OFF_SET_DEFAULT;
    /**
     * 滚轮个数
     */
    private int mWheelSize = WHEEL_SIZE;
    /**
     * The constant Selected index
     */
    private int mCurrentPositon = 1;
    /**
     * 滚轮数据列表
     */
    private List<T> mList = null;
    /**
     * The constant Context
     */
    private Context context;
    /**
     * The constant Views
     */
    private DirectionalLayout views;
    /**
     * 附加文本画笔
     */
    private Paint mTextPaint;
    /**
     * 皮肤风格
     */
    private Skin mSkin = Skin.None;
    /**
     * 滚轮样式
     */
    private WheelViewStyle mStyle;
    /**
     * 副WheelView
     */
    private WheelView mJoinWheelView;
    /**
     * 副滚轮数据列表
     */
    private HashMap<String, List<T>> mJoinMap;
    /**
     * 每一项高度
     */
    private int mItemH = -1;
    /**
     * 是否循环滚动
     */
    private boolean mLoop = LOOP;
    /**
     * 添加滚轮选中位置附加文本
     */
    private String mExtraText;
    /**
     * 附加文本颜色
     */
    private int mExtraTextColor;
    /**
     * 附加文本大小
     */
    private int mExtraTextSize;
    /**
     * 附加文本外边距
     */
    private int mExtraMargin;
    /**
     * 附加文本是否加粗
     */
    private boolean mExtraTextBold;
    /**
     * 是否可点击
     */
    private boolean mClickable = CLICKABLE;
    /**
     * 适配器
     */
    private BaseWheelAdapter<T> mWheelAdapter;
    /**
     * 滚轮被选中
     */
    private OnWheelItemSelectedListener<T> mOnWheelItemSelectedListener;
    /**
     * 滚轮被点击
     */
    private OnWheelItemClickListener<T> mOnWheelItemClickListener;
    /**
     * 是否可以点击滚动
     */
    private boolean mClickToPosition = false;
    /**
     * 选中的文本内容
     */
    private String mCurrentText;
    /**
     * 原始数据
     */
    private List<T> mOrignalList = null;

    /**
     * The constant Event handler
     */
    private EventHandler mEventHandler = new EventHandler(EventRunner.getMainEventRunner());

    /**
     * WheelView instance
     *
     * @param context context
     */
    public WheelView(Context context) {
        this(context, null);
    }

    /**
     * WheelView instance
     *
     * @param context context
     * @param attrs attrs
     */
    public WheelView(Context context, AttrSet attrs) {
        this(context, attrs, "");
    }

    /**
     * WheelView instance
     *
     * @param context context
     * @param attrs attrs
     * @param defStyle def style
     */
    public WheelView(Context context, AttrSet attrs, String defStyle) {
        super(context, attrs, defStyle);
        init(context);
    }

    /**
     * Get offset int
     *
     * @return the int
     */
    public int getOffset() {
        return mOffset;
    }

    /**
     * Set offset
     *
     * @param offset offset
     */
    public void setOffset(int offset) {
        this.mOffset = offset;
    }

    /**
     * 获得滚轮样式
     *
     * @return style 滚轮风格
     */
    public WheelViewStyle getStyle() {
        return mStyle;
    }

    /**
     * 设置滚轮样式
     *
     * @param style 滚轮风格
     */
    public void setStyle(WheelViewStyle style) {
        mStyle = style;
    }

    /**
     * 获得皮肤风格
     *
     * @return skin 皮肤
     */
    public Skin getSkin() {
        return mSkin;
    }

    /**
     * 设置皮肤风格
     *
     * @param skin 皮肤
     */
    public void setSkin(Skin skin) {
        mSkin = skin;
    }

    /**
     * 获得滚轮数据总数
     *
     * @return 滚轮数据总数
     */
    public int getWheelCount() {
        return !WheelUtils.isEmpty(mList) ? mList.size() : 0;
    }

    /**
     * 设置选中行附加文本
     *
     * @param text 附加文本
     * @param textColor 文本颜色
     * @param textSize 文本大小
     * @param margin 距中心水平方向的距离
     */
    public void setExtraText(String text, int textColor, int textSize, int margin) {
        setExtraText(text, textColor, textSize, margin, false);
    }

    /**
     * 设置选中行附加文本
     *
     * @param text 附加文本
     * @param textColor 文本颜色
     * @param textSize 文本大小
     * @param margin 距中心水平方向的距离
     * @param textBold 文本是否加粗
     */
    public void setExtraText(String text, int textColor, int textSize, int margin, boolean textBold) {
        mExtraText = text;
        mExtraTextColor = textColor;
        mExtraTextSize = textSize;
        mExtraMargin = margin;
        mExtraTextBold = textBold;
    }

    /**
     * 设置滚轮个数
     *
     * @param wheelSize 滚轮个数
     */
    @Override
    public void setWheelSize(int wheelSize) {
        if ((wheelSize & 1) == 0) {
            throw new WheelViewException("wheel size must be an odd number.");
        }
        mWheelSize = wheelSize;
        if (mWheelAdapter != null) {
            mWheelAdapter.setWheelSize(wheelSize);
        }
        mOffset = (this.mWheelSize - 1) / 2;
    }

    /**
     * 设置滚轮是否循环滚动
     *
     * @param loop 是否循环滚动
     */
    @Override
    public void setLoop(boolean loop) {
        if (loop != mLoop) {
            mLoop = loop;
            setSelection(0);
            if (mWheelAdapter != null) {
                mWheelAdapter.setLoop(loop);
            }
        }
    }

    /**
     * 获取滚轮个数
     *
     * @return mWheelSize
     */
    public int getWheelSize() {
        return mWheelSize;
    }

    /**
     * 设置滚轮选中项是否可点击
     *
     * @param clickable 轮选中项是否可点击
     */
    @Override
    public void setWheelClickable(boolean clickable) {
        if (clickable != mClickable) {
            mClickable = clickable;
            if (mWheelAdapter != null) {
                mWheelAdapter.setClickable(clickable);
            }
        }
    }

    /**
     * 设置是否支持点击滚轮进行选择
     *
     * @param clickToPosition 是否支持点击滚轮进行选择
     */
    public void setClickToPosition(boolean clickToPosition) {
        mClickToPosition = clickToPosition;
    }

    /**
     * 设置滚轮数据
     *
     * @param list 数据集合
     */
    @Override
    public void setWheelData(List<T> list) {
        if (WheelUtils.isEmpty(list)) {
            throw new WheelViewException("wheel datas are error.");
        }

        addDrawTask(this::onDraw, DrawTask.BETWEEN_BACKGROUND_AND_CONTENT);

        if (mList == null) {
            mList = new ArrayList<T>();
        }
        views.removeAllComponents();
        mList.clear();
        if (mLoop) {
            mOrignalList = new ArrayList<T>();
            mOrignalList.addAll(list);
            for (int i = 0; i < 2; i++) {
                mList.addAll(list);
            }
            mCurrentPositon = 22;
        } else {
            mList.addAll(list);
        }

        /**
         * 前面和后面补全
         */
        for (int i = 0; i < mOffset; i++) {
            if (list.get(0) instanceof WheelData) {
                mList.add(0, (T) new WheelData());
                mList.add((T) new WheelData());
            } else {
                mList.add(0, (T) "");
                mList.add((T) "");
            }
        }

        initData();

        mEventHandler.postTask(new Runnable() {
            @Override
            public void run() {
                WheelView.this.scrollTo(0, getSeletedIndex() * getHeight() / mWheelSize);
            }
        }, 100);
    }

    /**
     * 设置滚轮数据源适配器
     *
     * @param adapter 适配器
     */
    @Override
    public void setWheelAdapter(BaseWheelAdapter<T> adapter) {
        mWheelAdapter = adapter;
    }

    /**
     * 连接副WheelView
     *
     * @param wheelView 对象
     */
    @Override
    public void join(WheelView wheelView) {
        if (wheelView == null) {
            throw new WheelViewException("wheelview cannot be null.");
        }
        mJoinWheelView = wheelView;
    }

    /**
     * 副WheelView数据
     *
     * @param map 集合
     */
    public void joinDatas(HashMap<String, List<T>> map) {
        mJoinMap = map;
    }

    /**
     * On refreshed
     *
     * @param component component
     */
    @Override
    public void onRefreshed(Component component) {
        mEventHandler.postTask(new Runnable() {
            @Override
            public void run() {
                invalidate();
            }
        });
    }

    /**
     * On draw
     *
     * @param component component
     * @param canvas canvas
     */
    @Override
    public void onDraw(Component component, Canvas canvas) {
        DrawableFactory.createDrawable(canvas, mSkin, getWidth(),
                getHeight(), mStyle, mWheelSize, getHeight() / mWheelSize);
        if (!TextUtils.isEmpty(mExtraText)) {
            Rect targetRect = new Rect(0, mItemH * (mWheelSize / 2), getWidth(), mItemH * (mWheelSize / 2 + 1));
            mTextPaint.setTextSize(mExtraTextSize);
            mTextPaint.setColor(new Color(mExtraTextColor));
            Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();
            int baseline = (int) ((
                    targetRect.bottom + targetRect.top - (double) fontMetrics.bottom - (double) fontMetrics.top) / 2);
            mTextPaint.setTextAlign(TextAlignment.CENTER);
            mTextPaint.setFakeBoldText(mExtraTextBold);
            canvas.drawText(mTextPaint, mExtraText, targetRect.getCenterX() + mExtraMargin,
                    baseline);
        }
    }

    /**
     * On scrolled
     */
    @Override
    public void onScrolled() {
        int scrollValue = getScrollValue(AXIS_Y);
        refreshItemView(scrollValue);
    }

    /**
     * init
     *
     * @param context context
     */
    private void init(Context context) {
        if (mStyle == null) {
            mStyle = new WheelViewStyle();
        }
        mTextPaint = new Paint();
        getComponentTreeObserver().addScrolledListener(this);
        setTouchEventListener(this);

        setLayoutRefreshedListener(this);
        this.context = context;
        this.enableScrollBar(AXIS_Y, false);
        views = new DirectionalLayout(context);
        views.setOrientation(DirectionalLayout.VERTICAL);
        this.addComponent(views);
        mScrollerTask = new ScrollerRunnable();
    }

    /**
     * ScrollerRunnable 滑动监听线程
     */
    private class ScrollerRunnable implements Runnable {
        @Override
        public void run() {
            int newY = getScrollValue(AXIS_Y);
            if (mInitialY - newY == 0) {
                onScrollStopped();
            } else {
                mInitialY = getScrollValue(AXIS_Y);
                mEventHandler.postTask(mScrollerTask, mNewCheckDelay);
            }
        }
    }

    /**
     * onScrollStopped stopped
     */
    private void onScrollStopped() {
        final int remainder = mInitialY % mItemH;
        final int divided = mInitialY / mItemH;
        if (remainder == 0) {
            mCurrentPositon = divided + mOffset;
            onSeletedCallBack();
        } else if (remainder > mItemH / 2) {
            mEventHandler.postTask(new Runnable() {
                @Override
                public void run() {
                    WheelView.this.fluentScrollTo(0, mInitialY - remainder + mItemH);
                    mCurrentPositon = divided + mOffset + 1;
                    onSeletedCallBack();
                }
            });
        } else {
            mEventHandler.postTask(new Runnable() {
                @Override
                public void run() {
                    WheelView.this.fluentScrollTo(0, mInitialY - remainder);
                    mCurrentPositon = divided + mOffset;
                    onSeletedCallBack();
                }
            });
        }
    }

    /**
     * Start scroller task
     */
    public void startScrollerTask() {
        mInitialY = getScrollValue(AXIS_Y);
        mEventHandler.postTask(mScrollerTask, mNewCheckDelay);
    }

    /**
     * Init data
     */
    private void initData() {
        mWheelAdapter.setData(mList).setWheelSize(mWheelSize).setLoop(mLoop).setClickable(mClickable);
        mWheelSize = mOffset * 2 + 1;
        mItemH = getHeight() / mWheelSize;
        views.setLayoutConfig(new ComponentContainer.LayoutConfig(LayoutConfig.MATCH_PARENT,
                ComponentContainer.LayoutConfig.MATCH_CONTENT));
        for (T item : mList) {
            views.addComponent(createView(item));
        }

        refreshItemView(0);
    }

    /**
     * Create view text
     *
     * @param item item
     * @return the Component
     */
    private Component createView(T item) {
        Component cvItemRoot;
        if (mWheelAdapter instanceof ArrayWheelAdapter) {
            cvItemRoot = new WheelItem(context);
            cvItemRoot.setWidth(getWidth());
            ((WheelItem) cvItemRoot).setText(item.toString());
        } else if (mWheelAdapter instanceof SimpleWheelAdapter) {
            WheelData data = (WheelData) item;
            cvItemRoot = new WheelItem(context);
            cvItemRoot.setWidth(getWidth());
            ((WheelItem) cvItemRoot).setText(data.getName());
            ((WheelItem) cvItemRoot).setImage(data.getId());
        } else {
            cvItemRoot = LayoutScatter.getInstance(context).parse(ResourceTable.Layout_item_list, null, false);
            Text tvText = (Text) cvItemRoot.findComponentById(ResourceTable.Id_item_name);
            tvText.setText(item.toString());
        }
        cvItemRoot.setHeight(mItemH);
        cvItemRoot.setClickedListener(new ClickedListener() {
            @Override
            public void onClick(Component component) {
                onItemViewClick(component, item);
            }
        });
        return cvItemRoot;
    }

    private void onItemViewClick(Component component, T item) {
        if (mClickable) {
            if (component.getAlpha() == 1.0f) {
                component.setBackground(new ShapeElement(context, ResourceTable.Graphic_shape_item_pressed));
                context.getUITaskDispatcher().delayDispatch(() -> {
                    if (mOnWheelItemClickListener != null) {
                        mOnWheelItemClickListener.onItemClick(getSeletedIndex(), item);
                    }
                    component.setBackground(new ShapeElement(context, ResourceTable.Graphic_shape_item_normal));
                }, 200);
            }
        } else if (mClickToPosition) {
            Pattern pattern = Pattern.compile("\\d+");
            Matcher matcher = pattern.matcher(item.toString());
            int index;
            if (matcher.find()) {
                index = Integer.valueOf(matcher.group());
            } else {
                return;
            }
            mCurrentPositon = index + getOffset();
            WheelView.this.fluentScrollTo(0, index * mItemH);
        } else {
            mClickToPosition = false;
        }
    }

    /**
     * Refresh item view
     *
     * @param scrollValue scrollValue
     */
    private void refreshItemView(int scrollValue) {
        int position;
        int remainder = scrollValue % mItemH;
        int divided = scrollValue / mItemH;

        if (remainder == 0) {
            position = divided + mOffset;
        } else {
            if (remainder > mItemH / 2) {
                position = divided + mOffset + 1;
            } else {
                position = divided + mOffset;
            }
        }

        int childSize = views.getChildCount();
        for (int index = 0; index < childSize; index++) {
            Component component = views.getComponentAt(index);
            if (component == null) {
                return;
            }
            if (mWheelAdapter instanceof SimpleWheelAdapter || mWheelAdapter instanceof ArrayWheelAdapter) {
                refreshTextView(index, position, component, ((WheelItem) component).getText());
            } else {
                refreshTextView(index, position, component, WheelUtils.findTextView(context, component));
            }
        }
    }

    /**
     * 刷新文本
     *
     * @param position 位置
     * @param curPosition 选中位置
     * @param itemView 父控件
     * @param textView text控件
     */
    private void refreshTextView(int position, int curPosition, Component itemView, Text textView) {
        if (curPosition == position) {
            /**
             * 选中
             */
            int textColor = mStyle.selectedTextColor != -1 ? mStyle
                    .selectedTextColor : (mStyle.textColor != -1 ? mStyle
                    .textColor : WheelConstants.WHEEL_TEXT_COLOR);
            float defTextSize = mStyle.textSize != -1 ? mStyle.textSize :
                    WheelConstants.WHEEL_TEXT_SIZE;
            float textSize = mStyle.selectedTextSize != -1 ? mStyle
                    .selectedTextSize : (mStyle.selectedTextZoom != -1 ?
                    (defTextSize * mStyle.selectedTextZoom) :
                    defTextSize);
            boolean textBold = mStyle.selectedTextBold;
            mCurrentText = textView.getText();
            if (mJoinWheelView != null) {
                onSeletedCallBack();
            }
            setTextView(itemView, textView, textColor, textSize, 1.0f, textBold);
        } else {
            /**
             * 未选中
             */
            int textColor = mStyle.textColor != -1 ? mStyle.textColor :
                    WheelConstants.WHEEL_TEXT_COLOR;
            float textSize = mStyle.textSize != -1 ? mStyle.textSize :
                    WheelConstants.WHEEL_TEXT_SIZE;
            int delta = Math.abs(position - curPosition);
            float alpha = (float) Math.pow(mStyle.textAlpha != -1 ? mStyle.textAlpha :
                    WheelConstants.WHEEL_TEXT_ALPHA, delta);
            setTextView(itemView, textView, textColor, textSize, alpha, false);
        }
    }

    /**
     * 设置TextView
     *
     * @param itemView 父控件
     * @param textView Text控件
     * @param textColor Text字体颜色
     * @param textSize Text字体大小
     * @param textAlpha 透明度
     * @param textBold 字体加粗
     */
    private void setTextView(Component itemView, Text textView, int textColor, float textSize,
            float textAlpha, boolean textBold) {
        textView.setTextColor(new Color(textColor));
        textView.setTextSize((int) textSize, Text.TextSizeType.FP);
        itemView.setAlpha(textAlpha);
        if (textBold) {
            Font typeface = new Font.Builder("BOLD").setWeight(Font.MEDIUM).build();
            textView.setFont(typeface);
        }
    }

    /**
     * 设置滚轮选中项点击事件
     *
     * @param onWheelItemClickListener item点击监听
     */
    public void setOnWheelItemClickListener(OnWheelItemClickListener<T> onWheelItemClickListener) {
        mOnWheelItemClickListener = onWheelItemClickListener;
    }

    /**
     * On seleted call back
     *
     * @throws WheelViewException 异常
     */
    private void onSeletedCallBack() {
        if (mLoop) {
            onLoopSeletedCallBack();
        }
        if (mClickable && mOnWheelItemSelectedListener != null) {
            mOnWheelItemSelectedListener.onItemSelected(getSeletedIndex(), mList.get(mCurrentPositon));
        }
        if (mJoinWheelView != null) {
            onJoinSeletedCallBack();
        }
        mWheelAdapter.setCurrentPosition(mCurrentPositon);
    }

    private void onLoopSeletedCallBack() {
        if (getSeletedIndex() >= (mList.size() - 3 * mOffset - 1 - mOrignalList.size())) {
            views.removeComponents(mList.size() - mOffset, mOffset);
            List<T> tempList = new ArrayList<T>();
            tempList.addAll(mOrignalList);
            for (int i = 0; i < mOffset; i++) {
                mList.remove(mList.size() - 1);
                tempList.add((T) new WheelData());
            }
            mList.addAll(tempList);
            for (T item : tempList) {
                views.addComponent(createView(item));
            }
            if (((WheelData) (mOrignalList.get(mOrignalList.size() - 1))).getName().equals(
                    ((WheelData) (mList.get(mCurrentPositon))).getName())) {
                onScrolled();
            }
        } else if (getSeletedIndex() <= mOffset + mOrignalList.size()) {
            WheelView.this.scrollTo(0, (getSeletedIndex() + mOrignalList.size()) * mItemH);

            mCurrentPositon = mCurrentPositon + mOrignalList.size();
            startScrollerTask();
        } else {
            mLoop = true;
        }
    }

    private void onJoinSeletedCallBack() {
        if (!mJoinMap.isEmpty()) {
            if (TextUtils.isEmpty(mCurrentText)) {
                if (mCurrentPositon >= mList.size()) {
                    mJoinWheelView.resetDataFromTop(mJoinMap.get(mList.get(mList.size() - 1)));
                } else {
                    mJoinWheelView.resetDataFromTop(mJoinMap.get(mList.get(mCurrentPositon)));
                }
            } else {
                mJoinWheelView.resetDataFromTop(mJoinMap.get(mCurrentText));
            }
        } else {
            throw new WheelViewException("JoinList is error.");
        }
    }

    /**
     * 重置数据
     *
     * @param list 数据集合
     * @throws WheelViewException 异常
     */
    public void resetDataFromTop(final List<T> list) {
        if (WheelUtils.isEmpty(list)) {
            throw new WheelViewException("join map data is error.");
        }
        mEventHandler.postTask(new Runnable() {
            @Override
            public void run() {
                if (getSeletedIndex() >= list.size()) {
                    setSelection(list.size() - 1);
                }
                setWheelData(list);

                refreshItemView(getSeletedIndex() * mItemH);
            }
        }, 10);
    }

    /**
     * 获取滚轮位置
     *
     * @return 滚轮位置
     */
    public int getSelection() {
        return mCurrentPositon - mOffset;
    }

    /**
     * 设置滚轮位置
     *
     * @param selection 滚轮位置
     */
    public void setSelection(final int selection) {
        final int nowPosition = selection;
        mCurrentPositon = nowPosition + mOffset;
    }

    /**
     * Get seleted index int
     *
     * @return 真实的index
     */
    public int getSeletedIndex() {
        return mCurrentPositon - mOffset;
    }

    /**
     * 获取当前滚轮位置
     *
     * @return mCurrentPositon
     */
    public int getCurrentPosition() {
        return mCurrentPositon;
    }

    /**
     * 获取当前滚轮位置的数据
     *
     * @return item
     */
    public T getSelectionItem() {
        int position = getCurrentPosition();
        position = Math.max(position, 0);
        if (mList != null && mList.size() > position) {
            return mList.get(position);
        }
        return mList.get(0);
    }

    /**
     * Do fling y
     *
     * @param velocityY velocity y
     */
    @Override
    public void doFlingY(int velocityY) {
        super.doFlingY(velocityY / 4);
    }

    /**
     * Do fling
     *
     * @param velocityX velocity x
     * @param velocityY velocity y
     */
    @Override
    public void doFling(int velocityX, int velocityY) {
        super.doFling(velocityX, velocityY);
    }


    /**
     * Fluent scroll by
     *
     * @param dx dx
     * @param dy dy
     */
    @Override
    public void fluentScrollBy(int dx, int dy) {
        super.fluentScrollBy(dx, dy);
    }

    /**
     * On touch event boolean
     *
     * @param component component
     * @param event event
     * @return the boolean
     */
    @Override
    public boolean onTouchEvent(Component component, TouchEvent event) {
        if (event.getAction() == TouchEvent.PRIMARY_POINT_UP) {
            startScrollerTask();
        }
        return true;
    }

    /**
     * 设置滚轮滑动停止时事件，监听滚轮选中项
     *
     * @param onWheelItemSelectedListener 选中监听
     */
    public void setOnWheelItemSelectedListener(
            OnWheelItemSelectedListener<T> onWheelItemSelectedListener) {
        mOnWheelItemSelectedListener = onWheelItemSelectedListener;
    }

    /**
     * 滚轮皮肤
     */
    public enum Skin {
        Common, Holo, None
    }

    /**
     * OnWheelItemSelectedListener
     *
     * @param <T> item
     */
    public interface OnWheelItemSelectedListener<T> {
        /**
         * onItemSelected
         *
         * @param position 选中位置
         * @param item item
         */
        void onItemSelected(int position, T item);
    }

    /**
     * OnWheelItemClickListener
     *
     * @param <T> item
     */
    public interface OnWheelItemClickListener<T> {
        /**
         * onItemClick
         *
         * @param position 点击位置
         * @param item item
         */
        void onItemClick(int position, T item);
    }

    /**
     * WheelViewStyle 滚轮样式类
     */
    public static class WheelViewStyle {
        /**
         * 背景颜色
         */
        public int backgroundColor = -1;
        /**
         * holo样式边框颜色
         */
        public int holoBorderColor = -1;
        /**
         * holo样式边框宽度
         */
        public int holoBorderWidth = -1;
        /**
         * 文本颜色
         */
        public int textColor = -1;
        /**
         * 选中文本颜色
         */
        public int selectedTextColor = -1;
        /**
         * 文本大小
         */
        public int textSize = -1;
        /**
         * 选中文本大小
         */
        public int selectedTextSize = -1;
        /**
         * 文本透明度(0f ~ 1f)
         */
        public float textAlpha = -1;
        /**
         * 选中文本放大倍数
         */
        public float selectedTextZoom = -1;
        /**
         * 选中文本是否加粗
         */
        public boolean selectedTextBold;

        /**
         * WheelViewStyle instance
         */
        public WheelViewStyle() {
        }

        /**
         * WheelViewStyle instance
         *
         * @param style 滚轮样式
         */
        public WheelViewStyle(WheelViewStyle style) {
            this.backgroundColor = style.backgroundColor;
            this.holoBorderColor = style.holoBorderColor;
            this.holoBorderWidth = style.holoBorderWidth;
            this.textColor = style.textColor;
            this.selectedTextColor = style.selectedTextColor;
            this.textSize = style.textSize;
            this.selectedTextSize = style.selectedTextSize;
            this.textAlpha = style.textAlpha;
            this.selectedTextZoom = style.selectedTextZoom;
            this.selectedTextBold = style.selectedTextBold;
        }
    }
}
